﻿using mozhi.smarterp.Business.Enums;
using Mozhi.Abp.Domain.BasicData;
using System;
using Volo.Abp;
using Volo.Abp.Domain.Entities.Auditing;
using Volo.Abp.MultiTenancy;

namespace mozhi.smarterp.Business.Products
{
    public class ProductInventorySetting : AuditedAggregateRoot<Guid>, IMultiTenant
    {
        public Guid? TenantId { get; private set; }

        public Guid ProductId { get; private set; }

        public Product Product { get; private set; }

        /// <summary>
        /// 计价方式
        /// </summary>
        public ProductPricingType PricingType { get; private set; }

        /// <summary>
        /// 默认仓库
        /// </summary>
        public Guid DefaultWarehouseId { get; private set; }

        public Warehouse DefaultWarehouse {  get; private set; }

        /// <summary>
        /// 默认库位
        /// </summary>
        public Guid? DefaultLocationId { get; private set; }

        /// <summary>
        /// 启用批号
        /// </summary>
        public bool EnableBatchNumber {  get; private set; }

        /// <summary>
        /// 启用保质
        /// </summary>
        public bool EnableShelfLife {  get; private set; }

        /// <summary>
        /// 保质期天数
        /// </summary>
        public decimal? ShelfLifeDays {  get; private set; }

        /// <summary>
        /// 启用序列号
        /// </summary>
        public bool EnableSerialNumber {  get; private set; }

        /// <summary>
        /// 最小库存
        /// </summary>
        public decimal? MinStockQuantity {  get; private set; }

        /// <summary>
        /// 最大库存
        /// </summary>
        public decimal? MaxStockQuantity { get; private set; }

        /// <summary>
        /// 安全库存
        /// </summary>
        public decimal? SafetyStockQuantity { get; private set; }

        /// <summary>
        /// 再订货点
        /// </summary>
        public decimal? ReorderPointQuantity {  get; private set; }

        private ProductInventorySetting() { }

        public ProductInventorySetting(Guid id, Product product, ProductPricingType pricingType,  Warehouse defaultWarehouse, Guid? defaultLocationId, bool enableBatchNumber, bool enableShelfLife, 
            decimal? shelfLifeDays, bool enableSerialNumber, decimal? minStockQuantity, decimal? maxStockQuantity, decimal? safetyStockQuantity, decimal? reorderPointQuantity)
        {
            Id = id;

            Product = product;
            ProductId = Product == null ? default : Product.Id;
            PricingType = pricingType;

            DefaultWarehouse = defaultWarehouse;
            DefaultWarehouseId = DefaultWarehouse==null ? default : DefaultWarehouse.Id;
            DefaultLocationId = defaultLocationId;

            EnableBatchNumber = enableBatchNumber;
            EnableShelfLife = enableShelfLife;
            ShelfLifeDays = shelfLifeDays;
            EnableSerialNumber = enableSerialNumber;
            MinStockQuantity = minStockQuantity;
            MaxStockQuantity = maxStockQuantity;
            SafetyStockQuantity = safetyStockQuantity;
            ReorderPointQuantity = reorderPointQuantity;

            Validate();
        }

        public void Change(Product product, ProductPricingType pricingType, Warehouse defaultWarehouse, Guid? defaultLocationId, bool enableBatchNumber, bool enableShelfLife, decimal? shelfLifeDays, bool enableSerialNumber, decimal? minStockQuantity, decimal? maxStockQuantity, decimal? safetyStockQuantity, decimal? reorderPointQuantity)
        {
            Product = product;
            ProductId = Product == null ? default : Product.Id;
            PricingType = pricingType;

            DefaultWarehouse = defaultWarehouse;
            DefaultWarehouseId = DefaultWarehouse == null ? default : DefaultWarehouse.Id;
            DefaultLocationId = defaultLocationId;

            EnableBatchNumber = enableBatchNumber;
            EnableShelfLife = enableShelfLife;
            ShelfLifeDays = shelfLifeDays;
            EnableSerialNumber = enableSerialNumber;
            MinStockQuantity = minStockQuantity;
            MaxStockQuantity = maxStockQuantity;
            SafetyStockQuantity = safetyStockQuantity;
            ReorderPointQuantity = reorderPointQuantity;

            Validate();
        }

        public void ValidateProductInventory(decimal quantity, string batchNumber, string serialNumber, DateTime? productionDate)
        {
            if (EnableBatchNumber && batchNumber.IsNullOrEmpty())
                throw new UserFriendlyException("产品启用了批号，批号为必填", "100000");

            if (EnableSerialNumber && serialNumber.IsNullOrEmpty())
                throw new UserFriendlyException("产品启用了序列号，序列号为必填", "100000");

            if (EnableSerialNumber && quantity != 1)
                throw new UserFriendlyException("产品启用了序列号，数量只能为1", "100000");

            if (EnableShelfLife && !productionDate.HasValue)
                throw new UserFriendlyException("产品启用了保质期，生产日期为必填", "100000");
        }

        #region
        private void Validate()
        {

            if (Product == null)
                throw new UserFriendlyException("产品不存在", "100000");

            Product.Validate();

            if (DefaultWarehouse == null)
                throw new UserFriendlyException("仓库不存在", "100000");

            DefaultWarehouse.Validate();

            DefaultWarehouse.ValidateLoaction(DefaultLocationId);

            if (EnableBatchNumber && EnableSerialNumber)
                throw new UserFriendlyException("批号和序列号不能同时启用","100000");

            if (EnableShelfLife && !ShelfLifeDays.HasValue)
                throw new UserFriendlyException("启用保质期需要填写保质期天数", "100000");

            if (EnableShelfLife && ShelfLifeDays <= 0)
                throw new UserFriendlyException("保质期天数必须大于0");

            Check.NotDefaultOrNull<Guid>(ProductId , nameof(ProductId));

            Check.NotDefaultOrNull<Guid>(DefaultWarehouseId, nameof(DefaultWarehouseId));
        }
        #endregion
    }
}
